home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / mach / sun3.md / machTrap.s < prev    next >
Text File  |  1992-12-18  |  16KB  |  681 lines

  1. |* machTrap.s -
  2. |*
  3. |*     Contains the trap handlers.
  4. |*
  5. |* Copyright (C) 1985 Regents of the University of California
  6. |* All rights reserved.
  7. |*
  8.  
  9. #include <machConst.h>
  10. #include <machAsmDefs.h>
  11. #include <user/status.h>
  12.  
  13. .data
  14. .asciz "$Header: /cdrom/src/kernel/Cvsroot/kernel/mach/sun3.md/machTrap.s,v 9.6 92/06/17 13:23:59 jhh Exp $ SPRITE (Berkeley)"
  15. .even
  16. .text
  17.  
  18. |*
  19. |* ----------------------------------------------------------------------------
  20. |*
  21. |* Trap handling --
  22. |*
  23. |*    Handle exceptions.  In all cases except kernel calls, call
  24. |*    the C trap handler.  See the kernel call code below.
  25. |*
  26. |* Results:
  27. |*    None.
  28. |*
  29. |* Side effects:
  30. |*    None.
  31. |*
  32. |* ----------------------------------------------------------------------------
  33. |*
  34.     .globl    MachReset
  35. MachReset:
  36.     CallTrapHandler(MACH_RESET)
  37.  
  38.     .globl    MachBusError
  39. MachBusError:
  40.     CallTrapHandler(MACH_BUS_ERROR)
  41.  
  42.     .globl    MachAddrError
  43. MachAddrError:
  44.     CallTrapHandler(MACH_ADDRESS_ERROR)
  45.  
  46.     .globl    MachIllegalInst
  47. MachIllegalInst:
  48.     CallTrapHandler(MACH_ILLEGAL_INST)
  49.  
  50.     .globl    MachZeroDiv
  51. MachZeroDiv:
  52.     CallTrapHandler(MACH_ZERO_DIV)
  53.  
  54.     .globl    MachChkInst
  55. MachChkInst:
  56.     CallTrapHandler(MACH_CHK_INST)
  57.  
  58.     .globl    MachTrapv
  59. MachTrapv:
  60.     CallTrapHandler(MACH_TRAPV)
  61.  
  62.     .globl    MachPrivVio
  63. MachPrivVio:
  64.     CallTrapHandler(MACH_PRIV_VIOLATION)
  65.  
  66.     .globl    MachTraceTrap
  67. MachTraceTrap:
  68.     CallTrapHandler(MACH_TRACE_TRAP)
  69.  
  70.     .globl    MachEmu1010
  71. MachEmu1010:
  72.     CallTrapHandler(MACH_EMU1010)
  73.  
  74.     .globl    MachEmu1111
  75. MachEmu1111:
  76.     CallTrapHandler(MACH_EMU1111)
  77.  
  78.     .globl    MachFmtError    
  79. MachFmtError:
  80.     CallTrapHandler(MACH_STACK_FMT_ERROR)
  81.  
  82.     .globl    MachUninitVect
  83. MachUninitVect:
  84.     CallTrapHandler(MACH_UNINIT_VECTOR)
  85.  
  86.     .globl    MachSigRetTrap
  87. MachSigRetTrap:
  88.     CallTrapHandler(MACH_SIG_RET_TRAP)
  89.  
  90.     .globl    MachBadTrap
  91. MachBadTrap:
  92.     CallTrapHandler(MACH_BAD_TRAP)
  93.  
  94.     .globl    MachBrkptTrap
  95.     .globl _MachBrkptTrap
  96. _MachBrkptTrap:
  97. MachBrkptTrap:
  98.     CallTrapHandler(MACH_BRKPT_TRAP)
  99.  
  100. .globl MachFpUnorderedCond
  101. MachFpUnorderedCond:
  102.     CallTrapHandler(MACH_FP_UNORDERED_COND)
  103.  
  104. .globl MachFpInexactResult
  105. MachFpInexactResult:
  106.     CallTrapHandler(MACH_FP_INEXACT_RESULT)
  107.  
  108. .globl MachFpZeroDiv
  109. MachFpZeroDiv:
  110.     CallTrapHandler(MACH_FP_ZERO_DIV)
  111.  
  112. .globl MachFpUnderflow
  113. MachFpUnderflow:
  114.     CallTrapHandler(MACH_FP_UNDERFLOW)
  115.  
  116. .globl MachFpOperandError
  117. MachFpOperandError:
  118.     CallTrapHandler(MACH_FP_OPERAND_ERROR)
  119.  
  120. .globl MachFpOverflow
  121. MachFpOverflow:
  122.     CallTrapHandler(MACH_FP_OVERFLOW)
  123.  
  124. .globl MachFpNaN
  125. MachFpNaN:
  126.     CallTrapHandler(MACH_FP_NAN)
  127.  
  128.  
  129.  
  130. |*
  131. |* ----------------------------------------------------------------------
  132. |*
  133. |* MachUnixSyscallTrap --
  134. |*
  135. |*    This is the code entered on Unix compatible system call traps.
  136. |*    The code below is tuned to get into and out of kernel calls as
  137. |*      fast as possible.
  138. |*
  139. |* Results:
  140. |*    If the carry flag is clear, d0 contains the result of the system call.
  141. |*      If the carry flag is set, the system call failed, and d0 contains
  142. |*      the errno.
  143. |*
  144. |* Side effects:
  145. |*    Depends on the kernel call.
  146. |*
  147. |* ----------------------------------------------------------------------
  148. |*
  149.  
  150.     .globl MachUnixSyscallTrap
  151. MachUnixSyscallTrap:
  152.  
  153.     |* Save the address registers we use, and the sp.
  154.     |* We used to not save a0, a1, but the Sun longjmp code counts
  155.     |* on a0 being preserved.
  156.     movl    a0, sp@-
  157.     movl    a1, sp@-
  158.     movl    a2, sp@-
  159.     movl    a3, sp@-
  160.     movl    sp, a3
  161.  
  162.     movl    _machCurStatePtr, a0
  163.  
  164.     |* Save d0, because the Sigreturn system call needs it.
  165.     |* (Boneheaded SunOS convention for that system call!)
  166.     movl    d0, a0@(MACH_TRAP_REGS_OFFSET + 0)
  167.  
  168.  
  169.     |* Save the exc stack pointer since we need that too.
  170.     |* We should probably use special handling for some of this.
  171.     lea    sp@(16), a1
  172.     movl    a1, a0@(MACH_EXC_STACK_PTR_OFFSET)
  173.     |* Clear the carry bit to indicate no error.
  174.     movw    a1@, d0
  175.     andw    #~0x1, d0
  176.     movw    d0, a1@
  177.  
  178.     |* Pop the call number into d0
  179.     movc    usp, a1
  180.     movl    a1@+, d0
  181.     movc    a1, usp
  182.  
  183.     |*
  184.     |* Always save the user stack pointer because it can be needed
  185.     |* while processing the system call.
  186.     |*
  187.     movl    a1, a0@(MACH_USER_SP_OFFSET)
  188.  
  189.     |*
  190.     |* Store this kernel call in the last kernel call variable.
  191.     |*
  192.     movl    d0, a0@(MACH_LAST_SYS_CALL_OFFSET)
  193.  
  194.     |*
  195.     |* If this is a fork kernel call, save the registers in the PCB.
  196.     |* This is a hack, and should eventually go away by adding another
  197.     |* parameter to fork, which gives the address of an area of
  198.     |* memory containing the process' saved state.
  199.     |*
  200.  
  201.     cmpl    #2, d0
  202.     beqs    0f
  203.     cmpl    #66, d0
  204.     bnes    1f
  205. 0:
  206.     moveml    #0xffff, a0@(MACH_TRAP_REGS_OFFSET)
  207.     movl    sp@(0), a1    | a3
  208.     movl    a1, a0@(MACH_TRAP_REGS_OFFSET+48)
  209.     movl    sp@(4), a1    | a2
  210.     movl    a1, a0@(MACH_TRAP_REGS_OFFSET+44)
  211.     movl    sp@(8), a1    | a1
  212.     movl    a1, a0@(MACH_TRAP_REGS_OFFSET+40)
  213.     movl    sp@(12), a1    | a0
  214.     movl    a1, a0@(MACH_TRAP_REGS_OFFSET+32)
  215.  
  216.     SaveUserFpuState();
  217.  
  218. 1:
  219.     |*
  220.     |* Check number of kernel call for validity.
  221.     |*
  222.  
  223.     cmpl    _sysUnixNumSyscalls, d0
  224.     bges     2f
  225.  
  226.     |*
  227.     |* Copy the arguments from user space and push them onto the stack.
  228.     |*
  229.  
  230.     lsll    #3, d0
  231.     addl    #_sysUnixSysCallTable, d0
  232.     movl    d0, a2
  233.     movl    a2@(4), d1
  234.     movl    d1, sp@-
  235.     beqs    4f
  236.     subql   #1, d1
  237.     addl    #8, a1
  238.     lsll    #2, d1
  239.     addl    d1, a1
  240.     lsrl    #2, d1
  241.  
  242.     |* Allow page faults in the copy-in.
  243.  
  244.     .globl _MachFetchArgs2
  245. _MachFetchArgs2:
  246. 3:    
  247.     movl    a1@-, sp@-
  248.     dbra    d1, 3b
  249.     .globl _MachFetchArgsEnd2
  250. _MachFetchArgsEnd2:
  251. 4:
  252.     movl    a2@, a1
  253.     jsr     a1@
  254.  
  255.     |*
  256.     |* Disable interrupts and see if any special processing must
  257.     |* be done on the process.  Note:  this is checking the
  258.     |* specialHandling field of the process control block, and depends
  259.     |* on the fact that specialHandling follows immediately after the
  260.     |* kcallTable field.
  261.     |*
  262.  
  263.     movl    _machCurStatePtr, a0
  264.     movl    a0@(MACH_USER_SP_OFFSET), a2 | restore the (new) SP
  265.     movc    a2, usp
  266.  
  267.     movl    _proc_RunningProcesses, a0
  268.     movl    a0@, a2            | d1 now has PCB address.
  269.     addl    _machKcallTableOffset, a2
  270.                     | a2 now has address of kcallTable
  271.                     | field in PCB.
  272.     movw    #0x2700, sr        | Disable interrupts.
  273.     tstl    a2@(4)            | Check specialHandling
  274.     bnes    6f
  275. 5:
  276.     movl    a3, sp
  277.     movl    sp@+, a3
  278.     movl    sp@+, a2
  279.     movl    sp@+, a1
  280.     movl    sp@+, a0
  281.     cmpl    #-1, d0
  282.     beqs    7f
  283.     rte
  284. 7:
  285.     movw    sp@, d0        | Set the carry bit to indicate error
  286.     orw    #0x1, d0
  287.     movw    d0, sp@
  288.     movel    _proc_RunningProcesses,a0    | Move errno into d0
  289.     movel    a0@,a0
  290.     movel    a0@(MACH_UNIX_ERRNO_OFFSET),d0
  291.     rte
  292.  
  293. 2:
  294.     movl    a3, sp
  295.     movl    sp@+, a3
  296.     movl    sp@+, a2
  297.     movl    sp@+, a1
  298.     movl    sp@+, a0
  299.     movw    sp@, d0        | Set the carry bit to indicate error
  300.     orw    #0x1, d0
  301.     movw    d0, sp@
  302.     movel   #22, d0        | Return EINVAL
  303.     rte
  304.  
  305. 6:
  306.     |*
  307.     |* Something's up with the process (context switch, maybe, or
  308.     |* single-step mode?).  Restore the stack to what it was at
  309.     |* the beginning of the kernel call, then go through a slow
  310.     |* trap-processing procedure to take special action.
  311.     |*
  312.     |* We have to make sure we do the right thing with errno,
  313.     |* even if special handling is set.
  314.     |*
  315.  
  316.     movl    a3, sp            | Pop kcall args off stack.
  317.     |*clrl    a2@(4)
  318.     movw    #0x2000, sr
  319.     movl    sp@+, a3
  320.     movl    sp@+, a2
  321.     movl    sp@+, a1
  322.     movl    sp@+, a0
  323.     cmpl    #-1, d0
  324.     beqs    7f
  325.     CallTrapHandler(MACH_UNIX_SYSCALL_TRAP)
  326. 7:
  327.     movw    sp@, d0        | Set the carry bit to indicate error
  328.     orw    #0x1, d0
  329.     movw    d0, sp@
  330.     movel    _proc_RunningProcesses,a0    | Move errno into d0
  331.     movel    a0@,a0
  332.     movel    a0@(MACH_UNIX_ERRNO_OFFSET),d0
  333.     CallTrapHandler(MACH_UNIX_SYSCALL_TRAP)
  334.  
  335.  
  336. |*
  337. |* ----------------------------------------------------------------------
  338. |*
  339. |* MachSyscallTrap --
  340. |*
  341. |*    This is the code entered on system call traps.  The code below
  342. |*    is tuned to get into and out of kernel calls as fast as possible.
  343. |*
  344. |* Results:
  345. |*    Returns a status to the caller in d0.
  346. |*
  347. |* Side effects:
  348. |*    Depends on the kernel call.
  349. |*
  350. |* ----------------------------------------------------------------------
  351. |*
  352.  
  353.     .globl _machMaxSysCall, _machKcallTableOffset, _machArgOffsets
  354.     .globl _machArgDispatch, _machCurStatePtr
  355.     .globl _sys_NumCalls, _proc_RunningProcesses
  356.     .globl MachSyscallTrap
  357. MachSyscallTrap:
  358.  
  359.     |*
  360.     |* Always save the user stack pointer because it can be needed
  361.     |* while processing the system call.
  362.     |*
  363.     movl    _machCurStatePtr, a0
  364.     movc    usp, a1
  365.     movl    a1, a0@(MACH_USER_SP_OFFSET)
  366.  
  367.     |*
  368.     |* If this is a fork kernel call, save the registers in the PCB.
  369.     |* This is a hack, and should eventually go away by adding another
  370.     |* parameter to fork, which gives the address of an area of
  371.     |* memory containing the process' saved state.
  372.     |*
  373.  
  374.     tstl    d0
  375.     jne    1f
  376.     moveml    #0xffff, a0@(MACH_TRAP_REGS_OFFSET)
  377.     movl    sp, a0@(MACH_EXC_STACK_PTR_OFFSET)
  378.     SaveUserFpuState();
  379.  
  380.     |*
  381.     |* Save registers used here:  two address registers and sp.
  382.     |*
  383.  
  384. 1:    movl    a2, sp@-
  385.     movl    a3, sp@-
  386.     movl    sp, a3
  387.  
  388.     |*
  389.     |* Check number of kernel call for validity.
  390.     |*
  391.  
  392.     cmpl    _machMaxSysCall, d0
  393.     jls    2f
  394.     movl    #SYS_INVALID_SYSTEM_CALL, d0
  395.     jra    return
  396.  
  397. 2:
  398.     |*
  399.     |* Store this kernel call in the last kernel call variable.
  400.     |*
  401.     movl    d0, a0@(MACH_LAST_SYS_CALL_OFFSET)
  402.  
  403.     |*
  404.     |* Increment a count of the number of times this kernel call
  405.     |* has been invoked.
  406.     |*
  407.     asll    #2, d0            | Used to index into tables.
  408.     movl    #_sys_NumCalls, a0
  409.     addql    #1, a0@(0, d0:w)
  410.  
  411.     |*
  412.     |* Copy the arguments from user space and push them onto the
  413.     |* stack.  Note:  this code interacts heavily with the C code
  414.     |* in Mach_InitSyscall().  If you change one, be sure to change
  415.     |* the other.
  416.     |*
  417.  
  418.     movc    usp, d1
  419.     movl    #_machArgOffsets, a0
  420.     addl    a0@(0, d0:w), d1
  421.     movl    d1, a0
  422.     movl    #_machArgDispatch, a1
  423.     movl    a1@(0, d0:w), a1
  424.     jmp    a1@
  425.  
  426.     .globl _MachFetchArgs
  427. _MachFetchArgs:
  428.     movl    a0@-, sp@-        | 16 argument words.
  429.     movl    a0@-, sp@-
  430.     movl    a0@-, sp@-
  431.     movl    a0@-, sp@-
  432.     movl    a0@-, sp@-        | 12 argument words.
  433.     movl    a0@-, sp@-
  434.     movl    a0@-, sp@-
  435.     movl    a0@-, sp@-
  436.     movl    a0@-, sp@-        | 8 argument words.
  437.     movl    a0@-, sp@-
  438.     movl    a0@-, sp@-
  439.     movl    a0@-, sp@-
  440.     movl    a0@-, sp@-        | 4 argument words.
  441.     movl    a0@-, sp@-
  442.     movl    a0@-, sp@-
  443.     movl    a0@-, sp@-
  444.  
  445.     .globl _MachFetchArgsEnd
  446. _MachFetchArgsEnd:            | Marks last place where PC could be
  447.                     | when a page fault occurs while
  448.                     | fetching arguments.  Needed to
  449.                     | distinguish a page fault during
  450.                     | arg fetch (which is OK) from other
  451.                     | page faults in the kernel, which are
  452.                     | fatal errors.
  453.  
  454.     |*
  455.     |* Find the location in the current process's control block
  456.     |* of the trapFlags and kcallTable fields.  Then lookup the
  457.     |* address of the kernel-call handling routine and invoke it.
  458.     |*
  459.  
  460.     movl    _proc_RunningProcesses, a0
  461.     movl    a0@, d1            | d1 now has PCB address.
  462.     addl    _machKcallTableOffset, d1
  463.     movl    d1, a2            | a2 now has address of kcallTable
  464.                     | field in PCB.
  465.     movl    a2@, a0            | a0 points to 0th entry in table.
  466.     movl    a0@(0, d0:w), a1
  467.     jsr    a1@            | Dispatches to the top-level kernel
  468.                     | call procedure.
  469.  
  470.     |*
  471.     |* Disable interrupts and see if any special processing must
  472.     |* be done on the process.  Note:  this is checking the
  473.     |* specialHandling field of the process control block, and depends
  474.     |* on the fact that specialHandling follows immediately after the
  475.     |* kcallTable field, whose address was loaded into a2 above.
  476.     |*
  477.  
  478.     movl    a3, sp            | Pop kcall args off stack.
  479.     movw    #0x2700, sr        | Disable interrupts.
  480.     tstl    a2@(4)
  481.     jeq    return
  482.  
  483.     |*
  484.     |* Something's up with the process (context switch, maybe, or
  485.     |* single-step mode?).  Restore the stack to what it was at
  486.     |* the beginning of the kernel call, then go through a slow
  487.     |* trap-processing procedure to take special action.
  488.     |*
  489.  
  490.     clrl    a2@(4)
  491.     movw    #0x2000, sr
  492.     movl    sp@+, a3
  493.     movl    sp@+, a2
  494.     CallTrapHandler(MACH_SYSCALL_TRAP)
  495.  
  496. return:
  497.     movl    sp@+, a3
  498.     movl    sp@+, a2
  499.     rte
  500.  
  501. /*
  502.  *-------------------------------------------------------------------------
  503.  *
  504.  * MachReturnFromUserTrap --
  505.  *
  506.  *    Routine to return from a trap handler.  Called by CallTrapHandler
  507.  *    macro after have returned from MachTrap.  The proper action is
  508.  *    taken depending on the error code and then an rte to user space
  509.  *    is performed.
  510.  *
  511.  *-------------------------------------------------------------------------
  512.  */
  513.     .globl MachReturnFromUserTrap
  514. MachReturnFromUserTrap:
  515.  
  516. |*
  517. |* Take proper action depending on the return code.
  518. |*
  519.         cmpl     #MACH_OK, d0
  520.         beq     normReturn
  521.     cmpl    #MACH_KERN_ERROR, d0
  522.     beq    kernError
  523.     cmpl    #MACH_SIG_RETURN, d0
  524.     beq    sigReturn
  525. |*
  526. |* Bogus return code so trap to debugger.
  527. |*
  528.     jra     _Dbg_Trap
  529.  
  530. sigReturn:
  531. |*
  532. |* Are returning from a signal handler.  First get pointer to
  533. |* mach state structure.
  534. |*
  535.     movl    _machCurStatePtr, a0
  536. |*
  537. |* The saved stack pointer points to where the exception stack is to
  538. |* be restored at.
  539. |*
  540.     movl    a0@(MACH_TRAP_REGS_OFFSET + 60), sp
  541.     movl    sp, a0@(MACH_EXC_STACK_PTR_OFFSET)    
  542. |*
  543. |* Call bcopy((Address)excStack, (Address)sp, sizeof(excStack));
  544. |*
  545.     movl    sp, d0
  546.     movl    a0@(MACH_SIG_EXC_STACK_SIZE_OFFSET), sp@-
  547.     movl    d0, sp@-
  548. |*    movl    sp, sp@-
  549.     pea    a0@(MACH_SIG_EXC_STACK_OFFSET)
  550.     jsr    _bcopy
  551.     addl    #12, sp
  552. |*
  553. |* Call the normal return from trap return MachUserReturn(procPtr, &excStack)
  554. |* after enabling interrupts because they were disabled when we were called.
  555. |*
  556.     movw    #0x2000, sr
  557.     movl    _proc_RunningProcesses, a0
  558.     movl    a0@, sp@-
  559.     jsr    _MachUserReturn
  560. |*
  561. |* Do a normal return.
  562. |*
  563.     jra    normReturn
  564.  
  565. kernError:
  566. |*
  567. |* Got a fatal kernel error.  First sync disks, then restore the registers so
  568. |* that the debugger doesn't have to rely on being able to get registers from
  569. |* the proc table and then move the stack pointer back so that the trap code
  570. |* and bus error register are visible.
  571. |*
  572.     jsr    _Sys_SyncDisks
  573.     RestoreUserFpuState()
  574.     RestoreUserRegs()
  575.     subl    #MACH_TRAP_INFO_SIZE, sp
  576.     jra     _Dbg_Trap
  577.  
  578. normReturn:
  579. |*
  580. |* Normal return from trap (no errors).
  581. |*
  582.  
  583.     RestoreUserFpuState()
  584.     RestoreUserRegs()
  585.         rte
  586.  
  587.  
  588. /*
  589.  * ----------------------------------------------------------------------------
  590.  *
  591.  * RestoreKernRegs --
  592.  *
  593.  *      Restore the 4 saved temporary registers from the stack after moving
  594.  *    the stack pointer past the trap code and bus error register.
  595.  *
  596.  * ----------------------------------------------------------------------------
  597.  */
  598. #define RestoreKernRegs() \
  599.     addql    #8, sp; \
  600.     moveml    sp@+, #0x0303
  601.  
  602.  
  603. /*
  604.  *-------------------------------------------------------------------------
  605.  *
  606.  * MachReturnFromKernTrap --
  607.  *
  608.  *    Routine to return from a trap handler.  Called by CallTrapHandler
  609.  *    macro after have returned from MachTrap.  The proper action is
  610.  *    taken depending on the error code and then an rte to kern space
  611.  *    is performed.
  612.  *
  613.  *-------------------------------------------------------------------------
  614.  */
  615.     .globl MachReturnFromKernTrap
  616. MachReturnFromKernTrap:
  617.  
  618. |*
  619. |* Take proper action depending on the return code.
  620. |*
  621.         cmpl     #MACH_OK, d0
  622.         beq     kernNormReturn
  623.     cmpl    #MACH_KERN_ERROR, d0
  624.     beq    kernKernError
  625.     cmpl    #MACH_USER_ERROR, d0
  626.     beq    kernUserError
  627.  
  628. |*
  629. |* Bogus return code so trap to debugger.
  630. |*
  631.     jra     _Dbg_Trap
  632.  
  633. kernUserError:
  634. |*
  635. |* Got an error on a copy in from user space.  Blow away the
  636. |* exception stack and return SYS_ARG_NOACCESS to the function doing the copy.
  637. |* We have to compute the exception size of the exception stack from the
  638. |* vector offset register.
  639. |*
  640.     RestoreKernRegs()
  641.     clrl    d0
  642.     movw    sp@(6), d0        | D0 = VOR
  643.     lsrl    #8, d0            | DO >> 12 to get to stack format
  644.     lsrl    #4, d0
  645.     cmpl    #MACH_MC68010_BUS_FAULT, d0
  646.     bne    1f
  647.     addl    #MACH_MC68010_BUS_FAULT_SIZE, sp
  648.     bra    4f
  649. 1:    cmpl    #MACH_SHORT_BUS_FAULT, d0
  650.     bne    2f
  651.     addl    #MACH_SHORT_BUS_FAULT_SIZE, sp
  652.     bra    4f
  653. 2:    cmpl    #MACH_LONG_BUS_FAULT, d0
  654.     bne    3f
  655.     addl    #MACH_LONG_BUS_FAULT_SIZE, sp
  656.     bra    4f
  657. 3:    trap    #15
  658.  
  659. 4:    movl    #0x20000, d0
  660.     rts
  661.  
  662. kernKernError:
  663. |*
  664. |* Got a fatal kernel error.  First sync disks, then restore the registers so
  665. |* that the debugger doesn't have to rely on being able to get registers from
  666. |* the proc table and then move the stack pointer back so that the trap code
  667. |* and bus error register are visible.
  668. |*
  669.     jsr    _Sys_SyncDisks
  670.     RestoreKernRegs()
  671.     subl    #MACH_TRAP_INFO_SIZE, sp
  672.     jra     _Dbg_Trap
  673.  
  674. kernNormReturn:
  675. |*
  676. |* Normal return from trap (no errors).
  677. |*
  678.     RestoreKernRegs()
  679.         rte
  680.  
  681.